package com.xjrsoft.module.workflow.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.core.secure.XjrUser;
import com.xjrsoft.core.tool.utils.BeanUtil;
import com.xjrsoft.core.tool.utils.CollectionUtil;
import com.xjrsoft.core.tool.utils.StringPool;
import com.xjrsoft.module.base.entity.XjrBaseTempfield;
import com.xjrsoft.module.base.service.IXjrBaseTempfieldService;
import com.xjrsoft.module.workflow.dto.GetPageListNwfDelegateDto;
import com.xjrsoft.module.workflow.entity.XjrNwfDelegateRule;
import com.xjrsoft.module.workflow.entity.XjrNwfDelegaterelation;
import com.xjrsoft.module.workflow.entity.XjrNwfSchemeinfo;
import com.xjrsoft.module.workflow.mapper.XjrNwfDelegateruleMapper;
import com.xjrsoft.module.workflow.service.IXjrNwfDelegateRelationService;
import com.xjrsoft.module.workflow.service.IXjrNwfDelegateRuleService;
import com.xjrsoft.module.workflow.service.IXjrNwfSchemeInfoService;
import com.xjrsoft.module.workflow.vo.NwfDelegateVo;
import io.jsonwebtoken.lang.Collections;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class XjrNwfDelegateRuleServiceImpl extends ServiceImpl<XjrNwfDelegateruleMapper, XjrNwfDelegateRule> implements IXjrNwfDelegateRuleService {

    private IXjrNwfDelegateRelationService nwfDelegateRelationService;

    private IXjrNwfSchemeInfoService nwfSchemeInfoService;

    private TaskService taskService;

    private RepositoryService repositoryService;

    private HistoryService historyService;

    private IXjrBaseTempfieldService xjrBaseTempfieldService;
    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/9
     * @Param:[dto, fToUserName]
     * @return:com.xjrsoft.common.page.PageOutput<com.xjrsoft.module.workflow.entity.XjrNwfDelegaterule>
     * @Description:查询分页数据
     */
    @Override
    @SneakyThrows
    public PageOutput<NwfDelegateVo> selectDataPage(GetPageListNwfDelegateDto dto) {
        QueryWrapper<XjrNwfDelegateRule> query = new QueryWrapper<>();
        query.lambda().like(!StrUtil.hasBlank(dto.getKeyword()), XjrNwfDelegateRule::getToUserName, dto.getKeyword());
        IPage<XjrNwfDelegateRule> xjrNwfDelegateRuleIPage = baseMapper.selectPage(ConventPage.getPage(dto), query);
        List<NwfDelegateVo> nwfDelegateVos = BeanUtil.copyList(xjrNwfDelegateRuleIPage.getRecords(),NwfDelegateVo.class);
        for (int i = 0; i < nwfDelegateVos.size(); i++) {
            NwfDelegateVo nwfDelegateVo = nwfDelegateVos.get(i);
            List<XjrNwfDelegaterelation> delegaterelations = nwfDelegateRelationService.getByRuleId(nwfDelegateVo.getId());
            JSONArray nwfSchemeInfoIdList = new JSONArray();
            for (XjrNwfDelegaterelation xjrNwfDelegaterelation : delegaterelations) {
                JSONObject nwfSchemeInfoIdMap = new JSONObject();
                nwfSchemeInfoIdMap.put("F_Id", xjrNwfDelegaterelation.getSchemeInfoId());
                nwfSchemeInfoIdList.add(nwfSchemeInfoIdMap);
            }
            nwfDelegateVo.setNwfSchemeInfoIdList(nwfSchemeInfoIdList);
        }
        IPage<NwfDelegateVo> page = ConventPage.getPage(dto);
        return ConventPage.getPageOutput(page.setRecords(nwfDelegateVos).setTotal(baseMapper.selectCount(query)));
    }

    @Override
    @Transactional
    public boolean addOrUpdate(GetPageListNwfDelegateDto dto, XjrUser currentUser) throws Exception {
        String id = dto.getId();
        // 流程列表
        JSONArray schemeInfoList = dto.getSchemeInfoList();
        XjrNwfDelegateRule xjrNwfDelegateRule = BeanUtil.copy(dto, XjrNwfDelegateRule.class);
        // 新增
        if (StringUtils.isBlank(id)) {
            if (this.save(xjrNwfDelegateRule)) {
                // 关联表的主键
                ArrayList<String> nwfSchemeInfoIds = new ArrayList<>();
                for (int i = 0; i < schemeInfoList.size(); i++) {
                    nwfSchemeInfoIds.add(schemeInfoList.getJSONObject(i).getString("F_Id"));
                }
                if(CollectionUtil.isEmpty(nwfSchemeInfoIds)){
                    throw new Exception("未选择流程模板");
                }
                List<XjrNwfSchemeinfo> xjrNwfSchemeinfos = nwfSchemeInfoService.listByIds(nwfSchemeInfoIds);
                for (int i = 0; i < schemeInfoList.size(); i++) {
                    String nwfSchemeInfoId = schemeInfoList.getJSONObject(i).getString("F_Id");
                    XjrNwfDelegaterelation newXjrNwfDelegateRelation = new XjrNwfDelegaterelation();
                    newXjrNwfDelegateRelation.setDelegateRuleId(xjrNwfDelegateRule.getId());
                    newXjrNwfDelegateRelation.setSchemeInfoId(nwfSchemeInfoId);
                    boolean relationsave = nwfDelegateRelationService.save(newXjrNwfDelegateRelation);
                    if (!relationsave) {
                        log.info("关联表新增失败!");
                        return false;
                    }
                    XjrNwfSchemeinfo xjrNwfSchemeinfo = xjrNwfSchemeinfos.stream().filter(s -> s.getId().equals(nwfSchemeInfoId)).findAny().orElse(null);
                    if (xjrNwfSchemeinfo != null) {
                        processDelegate(xjrNwfSchemeinfo.getDeploymentId(), xjrNwfDelegateRule);
                    }
                }
            } else {
                log.info("委托信息表新增失败!");
                return false;
            }
        } else {
            // 更新
            // 委托信息表的更新
            xjrNwfDelegateRule.setCreateUserName(currentUser.getUserName());
            xjrNwfDelegateRule.setCreateUserId(currentUser.getUserId());
            if (this.updateById(xjrNwfDelegateRule)) {
                // 关系表的更新,先删除在新增
                List<XjrNwfDelegaterelation> relationList = nwfDelegateRelationService.getByRuleId(id);
                for (XjrNwfDelegaterelation xjrNwfDelegaterelation : relationList) {
                    boolean delete = nwfDelegateRelationService.removeById(xjrNwfDelegaterelation.getId());
                    if (!delete) {
                        log.info("关联表信息删除失败");
                        return false;
                    }
                }
                ArrayList<String> nwfSchemeInfoIds = new ArrayList<>();
                for (int i = 0; i < schemeInfoList.size(); i++) {
                    nwfSchemeInfoIds.add(schemeInfoList.getJSONObject(i).getString("F_Id"));
                }
                if(CollectionUtil.isEmpty(nwfSchemeInfoIds)){
                    throw new Exception("未选择流程模板");
                }
                List<XjrNwfSchemeinfo> xjrNwfSchemeinfos = nwfSchemeInfoService.listByIds(nwfSchemeInfoIds);
                // 新增
                for (int i = 0; i < schemeInfoList.size(); i++) {
                    JSONObject nwfSchemeInfoObj = schemeInfoList.getJSONObject(i);
                    String nwfSchemeInfoId = nwfSchemeInfoObj.getString("F_Id");
                    XjrNwfDelegaterelation delegaterelation = new XjrNwfDelegaterelation();
                    delegaterelation.setDelegateRuleId(id);
                    delegaterelation.setSchemeInfoId(nwfSchemeInfoId);
                    boolean save = nwfDelegateRelationService.save(delegaterelation);
                    if (!save) {
                        log.info("关联表信息更新新增失败");
                        return false;
                    }
                    XjrNwfSchemeinfo xjrNwfSchemeinfo = xjrNwfSchemeinfos.stream().filter(s -> s.getId().equals(nwfSchemeInfoId)).findAny().orElse(null);
                    if (xjrNwfSchemeinfo != null) {
                        processDelegate(xjrNwfSchemeinfo.getDeploymentId(), xjrNwfDelegateRule);
                    }
                }
            } else {
                return false;
            }
        }
        return true;
    }

    @Override
    @Transactional
    public boolean deleteDelegateRule(String ruleId) {
        XjrNwfDelegateRule xjrNwfDelegateRule = baseMapper.selectById(ruleId);
        if (xjrNwfDelegateRule != null) {
            boolean ruledelete = baseMapper.deleteById(ruleId) > 0;
            if (ruledelete) {
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("F_DelegateRuleId", ruleId);
                return nwfDelegateRelationService.remove(queryWrapper);
            }
        }
        return false;
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2021/3/18
     * @Param:[deploymentId]
     * @return:java.lang.String
     * @Description:
     */
    private void processDelegate(String deploymentId, XjrNwfDelegateRule xjrNwfDelegateRule) {
        LocalDateTime beginDate = xjrNwfDelegateRule.getBeginDate();
        LocalDateTime endDate = xjrNwfDelegateRule.getEndDate();
        String toUserId = xjrNwfDelegateRule.getToUserId();
        String createUserId = xjrNwfDelegateRule.getCreateUserId();
        LocalDateTime now = LocalDateTime.now();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
        if (processDefinition != null) {
            List<Task> list = taskService.createTaskQuery().processDefinitionKey(processDefinition.getKey()).list();
            if (!Collections.isEmpty(list)) {
                // 判断是否具备委托流程
                if (now.isAfter(beginDate) && now.isBefore(endDate)) {
                    //任务是否挂起
                    for (Task task : list) {
                            if(task.isSuspended()){
                                continue;
                            }
                        // 候选人
                        List<HistoricIdentityLink> userList = historyService.getHistoricIdentityLinksForTask(task.getId());
                        Set<String> userSet = userList.stream().map(s -> s.getUserId()).collect(Collectors.toSet());
                        String[] split = toUserId.split(StringPool.COMMA);
                        JSONArray userIds = new JSONArray();
                        for (String userId : split) {
                                if ((!StringUtils.equalsIgnoreCase(userId, createUserId))&&(!userSet.contains(userId))&&userSet.contains(createUserId)) {
                                    taskService.addCandidateUser(task.getId(), userId);
                                    userIds.add(userId);
                                }
                            }
                        if(CollectionUtil.isNotEmpty(userIds)) {
                            //添加委托信息
                            JSONObject delegateObj = new JSONObject();
                            delegateObj.put("createUserId", xjrNwfDelegateRule.getCreateUserId());
                            delegateObj.put("delegateUsers", userIds);
                            XjrBaseTempfield xjrBaseTempfield = new XjrBaseTempfield();
                            xjrBaseTempfield.setFkey(task.getId());
                            xjrBaseTempfield.setType("40");
                            xjrBaseTempfield.setCreateTime(new Date());
                            xjrBaseTempfield.setFvalue(delegateObj.toJSONString());
                            xjrBaseTempfieldService.save(xjrBaseTempfield);
                        }
                    }
                }
            }
        }
    }
}
